
package privatemessanger;
import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This class contains the socket of a client.
 * @author  Erez Fatal, Oren Slor, Elad Yanai, Sigal Agami, Chen Ben Shabat,
 *          Inbar Pardo, Islamm Heralla, Ziv Hadary, Oren Shalev, Ortal David.
 */
public class ConnectToHost extends Thread
{
    private String _string, _header;
    private Server _server;
    private Socket _s;
    private BufferedReader _in;
    private PrintWriter _out;

    /**
     * This is the ConnectToHost constructor.
     * @param IP The server's IP.
     * @throws Exception Faild to open socket.
     */
    public ConnectToHost(String IP) throws Exception
    {
        _s=new Socket(IP, MainFrame.PORT);
        _in=new BufferedReader(new InputStreamReader(_s.getInputStream()));
        OutputStream outstream = _s.getOutputStream();
        _out=new PrintWriter(outstream);
    }

    @Override
    /**
     * This method reads from the socket.
     */
    public void run()
    {
        try {
            writeSocket("HELLO "+MainFrame._user.getUserName()+" "+MainFrame._user.getType()+" "+MainFrame._user.getID()+" "+MainFrame._user.getIP());
            while(true)
            {
                _string = _in.readLine();
                parser(_string);
                if (_string.equals("OK_BYE") || _string.equals("DELETE_SERVER"))
                    break;
            }
        } catch (IOException ex) { Logger.getLogger(ConnectToHost.class.getName()).log(Level.SEVERE, null, ex); }
    }

    /**
     * This method creates a new thread.
     * @throws IOException Faild to create a new thread.
     */
    public void readSocket() throws IOException
    {
        Thread t=new Thread(this);
        t.start();
    }

    /**
     * This methood has to handle incoming messages.
     * @param str String from the socket.
     */
    void parser(String str)
    {
        int index;
        String[] words=str.split(" ");

        if (words[0].equals("WELCOME"))
        {
            _server=new Server(words[1]);
            _server.setServerName(words[2]);
            MainFrame._user.addServer(_server);
            index=MainFrame._user.getServerArray().indexOf(_server);
            MainFrame._user.getServerArray().get(index).addClient(MainFrame._user);
            MainFrame._serverName.updateList();
        }

        if (words[0].equals("NEW_CONTACT"))
        {
            index=MainFrame._user.getServerArray().indexOf(_server);
            int ID=Integer.decode(words[3]);
            if (MainFrame._user.getID()==ID)
                return;
            Client client=new Client(words[1], words[2], ID, words[4]);
            MainFrame._user.getServerArray().get(index).addClient(client);
            MainFrame._serverName.updateList();
        }

        if (words[0].equals("NEW_TYPE"))
        {
            index=MainFrame._user.getServerArray().indexOf(_server);
            int ID=Integer.decode(words[1]);
            MainFrame._user.getServerArray().get(index).getClient(ID, words[2]).setType(words[3]);
            MainFrame._serverName.updateList();
        }

        if (words[0].equals("REMOVE_CONTACT"))
        {
            index=MainFrame._user.getServerArray().indexOf(_server);
            int ID=Integer.decode(words[1]);
            MainFrame._user.getServerArray().get(index).removeClient(ID, words[2]);
            MainFrame._serverName.updateList();
        }

        if (words[0].equals("REMOVE_ALL"))
        {
            index=MainFrame._user.getServerArray().indexOf(_server);
            for (int i=2; i<MainFrame._user.getServerArray().get(index).getClientArray().size(); i++)
            {
                MainFrame._user.getServerArray().get(index).getClientArray().remove(i);
                i--;
            }
            MainFrame._serverName.updateList();
        }

        if (words[0].equals("DELETE_SERVER"))
        {
            index=MainFrame._user.getServerArray().indexOf(_server);
            MainFrame._user.getServerArray().remove(index);
            MainFrame._serverName.updateList();
            writeSocket("OK_DELETE");
        }

        if (words[0].equals("MESSAGE"))
        {
            _header=words[1]+" "+words[2]+" "+words[3]+" "+words[4]+" "+words[5];
            String message="";
            for (int i=6; i<words.length; i++)
            {
                if (message.equals(""))
                    message=words[6];
                else
                    message+=" "+words[i];
            }
            MainFrame._user.getMessageArray().add(Message.Create(_header,message));
            MainFrame._popUp.setText("You received a new message from "+MainFrame._user.getMessageArray().get(MainFrame._user.getMessageArray().size()-1).getSenderName());
            MainFrame._popUp.setVisible(true);
            MainFrame._message.cleanText();
            MainFrame._contactName.cleanSelectedClient();
            MainFrame._text.getSendButton().setEnabled(false);
            int contactIndex=MainFrame._contactName.getList().getSelectedIndex();
            int serverIndex=MainFrame._serverName.getList().getSelectedIndex();
            if (contactIndex!=-1 && serverIndex!=-1)
            {
                if (MainFrame._user.getServerArray().get(serverIndex).getClientArray().get(contactIndex).getID()!=MainFrame._user.getID())
                {
                    MainFrame._contactName.setSelectedClient(MainFrame._user.getServerArray().get(serverIndex).getClientArray().get(contactIndex));
                    MainFrame._text.getSendButton().setEnabled(true);
                    for (int i=0; i<MainFrame._user.getMessageArray().size(); i++)
                    {
                        if (MainFrame._user.getMessageArray().get(i).getSenderID()==MainFrame._user.getServerArray().get(serverIndex).getClientArray().get(contactIndex).getID() || MainFrame._user.getMessageArray().get(i).getReceiverID()==MainFrame._user.getServerArray().get(serverIndex).getClientArray().get(contactIndex).getID())
                            MainFrame._message.addText(MainFrame._user.getMessageArray().get(i));
                    }
                }
            }
            _header="";
        }
        if (words[0].equals("OK_BYE"))
            try {
                closeSocket();
            } catch (IOException ex) { Logger.getLogger(ConnectToHost.class.getName()).log(Level.SEVERE, null, ex); }
    }

    /**
     * This method writes to the socket.
     * @param str String to the socket.
     */
    public void writeSocket (String str)
    {
        _out.println(str);
        _out.flush();
    }

    /**
     * This method has to close the socket.
     * @throws IOException Faild to close socket.
     */
    public void closeSocket() throws IOException
    {
        try {
            _s.close();
        } catch(InterruptedIOException e) {System.out.println("Erroe Close Socket!!!"); }
    }
}
